package com.webex.ta.hydra;

import java.io.File;
import java.io.FilenameFilter;
import java.lang.reflect.Constructor;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.LinkedList;
import java.util.List;


/**
 * Created by Cisco WebEx.
 * User: vegaz
 * Date: 2010-9-27
 * Time: 17:04:56
 */
public class CoreClassLoader extends URLClassLoader {
    private static List<URL> jars;

    private static CoreClassLoader instance;

    ClassLoader pluginLoader;

    static {
        jars = new LinkedList<URL>();

        String hydraDir = HydraStartup.getHydraDir();

        /*
           * Does the system support UNC paths? If so, may need to fix them up
           * later
           */
        boolean usesUNC = System.getProperty("os.name").startsWith("Windows");

        StringBuffer classpath = new StringBuffer();
        File[] libDirs = new File[]{new File(hydraDir + File.separator + "lib"),
                new File(hydraDir + File.separator + "lib" + File.separator + "hydra")};
        for (File libDir : libDirs) {
            File[] libJars = libDir.listFiles(new FilenameFilter() {
                public boolean accept(File dir, String name) {
                    return name.endsWith(".jar");
                }
            });
            if (libJars == null) {
//                new Throwable("Could not access " + libDir).printStackTrace();
                continue;
            }
            for (File libJar : libJars) {
                try {
                    String s = libJar.getPath();

                    // Fix path to allow the use of UNC URLs
                    if (usesUNC) {
                        if (s.startsWith("\\\\") && !s.startsWith("\\\\\\")) {
                            s = "\\\\" + s;
                        } else if (s.startsWith("//") && !s.startsWith("///")) {
                            s = "//" + s;
                        }
                    } // usesUNC

                    jars.add(new URL("file", "", s));
                    classpath.append(System.getProperty("path.separator"));
                    classpath.append(s);
                } catch (MalformedURLException e) {
                    e.printStackTrace();
                }
            }
        }

        // ClassFinder needs this
        System.setProperty("java.class.path", System.getProperty("java.class.path") + classpath.toString());
    }

    private CoreClassLoader() {
        super(jars.toArray(new URL[jars.size()]));
        try {
            Class pluginLoaderClass = this.loadClass("com.webex.ta.hydra.plugin.PluginJarClassLoader", false);
            Constructor constructor = pluginLoaderClass.getConstructor(CoreClassLoader.class);
            pluginLoader = (ClassLoader)constructor.newInstance(this);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static CoreClassLoader getInstance() {
        if (instance == null)
            instance = new CoreClassLoader();
        return instance;
    }


    // Make it public
    @Override
    public Class<?> loadClass(String clazz, boolean resolve) throws ClassNotFoundException {
        try {
            return _loadClass(clazz, resolve);
        } catch (ClassNotFoundException e) {
            // ignore
        }

        Class cls = pluginLoader.loadClass(clazz);
        if (resolve)
            resolveClass(cls);
        return cls;
    }

    public Class<?> _loadClass(String clazz, boolean resolve) throws ClassNotFoundException {
        return super.loadClass(clazz, resolve);
    }
}
